package com.njtoyo.taxi.admin.service.platform.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.google.common.collect.Lists;
import com.njtoyo.taxi.admin.cache.SecondaryCachePutter;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.library.common.MapHelper;
import com.njtoyo.taxi.admin.mapper.secondary.entity.Role;
import com.njtoyo.taxi.admin.mapper.secondary.entity.RoleResourceMapping;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.AdminUserMapper;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.RoleMapper;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.RoleResourceMappingMapper;
import com.njtoyo.taxi.admin.rest.wrapper.platform.role.RoleCreateWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.platform.role.RoleListWrapper;
import com.njtoyo.taxi.admin.service.platform.RoleService;
import com.taxi.entity.common.RestResult;
import com.taxi.entity.common.ResultEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@DS(Const.SECONDARY_DS)
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleResourceMappingMapper roleResourceMappingMapper;

    @Autowired
    private SecondaryCachePutter secondaryCachePutter;

    @Autowired
    private AdminUserMapper adminUserMapper;

    @Override
    public RestResult findRolePage(RoleListWrapper roleListWrapper) {
        roleListWrapper.setOrders(Lists.newArrayList(new OrderItem("id", false)));
        IPage<Role> page = roleMapper.selectByPage(roleListWrapper);
        return RestResult.success(page);
    }

    @Override
    public RestResult findResource(Long roleId) {
        QueryWrapper<RoleResourceMapping> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", roleId);
        wrapper.select("resource_id");
        List<RoleResourceMapping> resource = roleResourceMappingMapper.selectList(wrapper);
        List<Long> resourceIds = resource.stream().map(RoleResourceMapping::getResourceId).collect(Collectors.toList());

        return RestResult.success(resourceIds);
    }

    @Override
    @Transactional
    public RestResult create(RoleCreateWrapper roleCreateWrapper) {
        // 校验 name 不重复
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        wrapper.eq("name", roleCreateWrapper.getName());
        if (roleMapper.selectOne(wrapper) != null) {
            return RestResult.failed("name 已经存在");
        }

        Role role = new Role();
        role.setName(roleCreateWrapper.getName());
        role.setTitle(roleCreateWrapper.getTitle());
        roleMapper.insert(role);

        List<Long> resources = roleCreateWrapper.getResourceIds();
        this.updateRoleResource(role.getId(), resources);

        return RestResult.success();
    }

    @Override
    @Transactional
    public RestResult update(Long roleId, Map params) {
        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        if (params.containsKey("resourceIds")) {
            List<Long> resources = MapHelper.convertList(params.get("resourceIds"));
            if (resources.isEmpty()) {
                return RestResult.failed("resourceIds 不能传空");
            }
            this.updateRoleResource(roleId, resources);
        }

        if (params.containsKey("title")) {
            role.setTitle(params.get("title").toString());
            roleMapper.updateById(role);
        }

        // 获取引用角色的用户,清除其缓存
        List<Long> ids = adminUserMapper.getAdminUserIdsByRoleId(roleId);
        if (CollUtil.isNotEmpty(ids)) {
            secondaryCachePutter.deleteAdminUserCache(ids);
        }

        return RestResult.success();
    }

    @Override
    @Transactional
    public RestResult delete(Long roleId) {
        // 判断角色是否存在
        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        // 判断角色是否被用户引用
        List<Long> adminUserIds = adminUserMapper.getAdminUserIdsByRoleId(roleId);
        if (adminUserIds.size() > 0) {
            return RestResult.failed("角色被用户引用,无法删除");
        }
        // 删除角色的所属权限
        QueryWrapper<RoleResourceMapping> mapping = new QueryWrapper<>();
        mapping.eq("role_id", roleId);
        roleResourceMappingMapper.delete(mapping);
        // 删除角色
        roleMapper.deleteById(roleId);

        return RestResult.success();
    }

    @Override
    public RestResult getAll() {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id, name, title");
        List<Role> res = roleMapper.selectList(queryWrapper);
        return RestResult.success(res);
    }

    private Boolean updateRoleResource(Long roleId, List<Long> resources) {
        // 删除原角色拥有的资源权限
        QueryWrapper<RoleResourceMapping> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", roleId);
        roleResourceMappingMapper.delete(wrapper);

        // 添加新的权限
        List<RoleResourceMapping> mappings = new ArrayList<>();
        resources.stream().forEach(id -> {
            RoleResourceMapping mapping = new RoleResourceMapping();
            mapping.setRoleId(roleId);
            mapping.setResourceId(id);
            mappings.add(mapping);
        });
        roleResourceMappingMapper.insertBatch(mappings);
        return true;
    }
}
